package com.soa.ws2http.util;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.util.StringUtils;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.soa.ws2http.util.JsonHelper.JsonFieldNameAs;
/**
 * <p>
 * json转换类<br>
 * 包含了:json转对象,对象转json双向以及各种转换策略
 * </p>
 * 
 *@category version 1.0
 *@author cy
 */
public class Json {
	private final static Gson GSON = new GsonBuilder()
			.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
			.registerTypeAdapter(Object.class, new NaturalDeserializer())
			.setPrettyPrinting().setDateFormat("yyyy-MM-dd").create();

	private final static Type MAPTYPE = new TypeToken<Map<String, String>>() {
	}.getType();

	private final static Type MAPTYPEOBJECT = new TypeToken<Map<String, Object>>() {
	}.getType();

	/** 获取 字段过滤 字段名更换策略的gson */
	private static Gson getFullGson(ExclusionStrategy exclusionStrategy,
			FieldNamingStrategy fieldNamingStrategy) {
		GsonBuilder gsonBuilder = new GsonBuilder();
		if (exclusionStrategy != null) {
			gsonBuilder.setExclusionStrategies(exclusionStrategy);
		}
		if (fieldNamingStrategy != null) {
			gsonBuilder.setFieldNamingStrategy(fieldNamingStrategy);
		}
		return gsonBuilder.registerTypeAdapterFactory(
				HibernateProxyTypeAdapter.FACTORY).setPrettyPrinting()
				.setDateFormat("yyyy-MM-dd").create();
	}

	/** 添加字段过滤策略 */
	private static ExclusionStrategy addExclusionStrategy(
			final boolean isFilter, String... fieldNames) {
		ExclusionStrategy strategy = null;
		if (fieldNames.length > 0) {
			final List<String> fieldNamesList = Arrays.asList(fieldNames);
			strategy = new ExclusionStrategy() {
				public boolean shouldSkipField(FieldAttributes field) {
					return isFilter ? fieldNamesList.contains(field.getName())
							: !fieldNamesList.contains(field.getName());
				}

				public boolean shouldSkipClass(Class<?> clazz) {
					// return false;
					return clazz == List.class || clazz == Set.class;
				}
			};
		}
		return strategy;
	}

	/** 添加字段转换策略 */
	private static FieldNamingStrategy addFieldNamingStrategy(
			final JsonFieldNameAs[] nameAs) {
		FieldNamingStrategy strategy = null;
		if (nameAs != null && nameAs.length > 0) {
			strategy = new FieldNamingStrategy() {
				public String translateName(Field field) {
					String name = field.getName();
					for (JsonFieldNameAs jsonFieldNameAs : nameAs) {
						if (jsonFieldNameAs.getOldName().equals(name)) {
							return jsonFieldNameAs.getNewName();
						}
					}
					return name;
				}
			};
		}
		return strategy;
	}

	/** 转换为json */
	private static String toJson(Object data, boolean isFilter,
			JsonFieldNameAs[] nameAs, String... fieldNames) {
		return getFullGson(addExclusionStrategy(isFilter, fieldNames),
				addFieldNamingStrategy(nameAs)).toJson(data);
	}

	/* public */

	/** 转换为JSON格式 */
	public static String toJson(Object data) {
		return GSON.toJson(data);
	}

	/** 根据所需字段,转换为JSON格式 */
	public static String toJsonByField(Object data, String... fieldNames) {
		return toJson(data, false, null, fieldNames);
	}

	/** 设置过滤字段,转换为JSON格式 */
	public static String toJsonFilterField(Object data, String... fieldNames) {
		return toJson(data, true, null, fieldNames);
	}

	/** 设置过滤字段,自定义转换字段的name,转换为JSON格式 */
	public static String toJsonFilterFieldAndNameAs(Object data,
			JsonFieldNameAs[] nameAs, String... fieldNames) {
		return toJson(data, true, nameAs, fieldNames);
	}

	/** 根据所需字段,自定义转换字段的name,转换为JSON格式 */
	public static String toJsonByFiledAndNameAs(Object data,
			JsonFieldNameAs[] nameAs, String... fieldNames) {
		return toJson(data, false, nameAs, fieldNames);
	}

	/** 把JSON字符转换为map */
	public static Map<String, String> formMap(String json) {
		if (StringUtils.isEmpty(json)) {
			return new HashMap<String, String>();
		}
		return GSON.fromJson(json, MAPTYPE);
	}

	/** 把JSON字符转换为Object-map */
	public static Map<String, Object> formMapByObject(String json) {
		if (StringUtils.isEmpty(json)) {
			return new HashMap<String, Object>();
		}
		return GSON.fromJson(json, MAPTYPEOBJECT);
	}

	/** 把JSON字符转换为对象 */
	public static <T> T formObject(Type type, String json) {
		return GSON.fromJson(json, type);
	}

}
